package com.my.demo.demo2.config;
import	java.util.Optional;
import	java.util.jar.JarFile;
import	java.io.FileInputStream;
import	java.util.zip.GZIPInputStream;
import	java.util.HashMap;
import	java.lang.reflect.Parameter;
import	java.lang.reflect.ParameterizedType;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.my.demo.demo2.annotation.ParamConvert;
import com.my.demo.demo2.util.SignUtil;
import com.my.demo.demo2.util.XmlUtil;
import okhttp3.FormBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author shanchong
 * @date 2019-07-12
 **/
public class LSConverterFactory extends Converter.Factory {

    public static Converter.Factory create(){
        return new LSConverterFactory();
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        return new LSResponseConverter(type);
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        return new LSRequestConverter(type,parameterAnnotations);
    }

    static final class LSResponseConverter implements Converter<ResponseBody, Object> {

        Class clazz;

        LSResponseConverter(Type type){
            this.clazz = (Class) type;
        }

        @Override
        public Object convert(ResponseBody value) {
            try {
                final String string = value.string();
                final String xml = URLDecoder.decode(string, "GBK");
                final Object o = clazz.newInstance();
                final Map<String, String> xml2Map = XmlUtil.xml2Map(xml);
                final Method[] methods = clazz.getMethods();
                for (final Method method : methods) {
                    final String name = method.getName();
                    if (name.startsWith("set")) {
                        final String setname = name.replace("set", "");
                        method.invoke(o, xml2Map.get(setname.substring(0, 1).toLowerCase() + setname.substring(1)));
                    }
                }
                return o;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }

    static final class LSRequestConverter implements Converter<Object,RequestBody> {

        private Class clazz;
        private Annotation[] parameterAnnotations;

        LSRequestConverter(Type clazz, Annotation[] parameterAnnotations){
            this.clazz = (Class) clazz;
            this.parameterAnnotations = parameterAnnotations;
        }

        @Override
        public RequestBody convert(Object value) throws IOException {
            final FormBody.Builder builder = new FormBody.Builder();
            final String sortParam = SignUtil.sortParam(value);
            final String sign = SignUtil.doSign(sortParam, privateKey);
            try {
                clazz.getMethod("setSign",String.class).invoke(value,sign);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }

            final Gson gson = new Gson();
            JsonObject jsonObject = new JsonObject();
            for (int i = 0; i < parameterAnnotations.length; i++) {
                final Annotation parameterAnnotation = parameterAnnotations[i];
                if (parameterAnnotation instanceof ParamConvert){
                    final String paramConvertJsonString = ((ParamConvert) parameterAnnotation).value();
                    jsonObject = gson.fromJson(paramConvertJsonString, JsonObject.class);
                }
            }

            final Method[] methods = clazz.getMethods();
            for (int i = 0; i < methods.length; i++) {
                final Method method = methods[i];
                final String name = method.getName();
                if (name.startsWith("get")&&!"getClass".equals(name)){
                    Object o = null;
                    try {
                        o = method.invoke(value);
                        if (o==null) {continue;}
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                    final String get = name.replace("get", "");

                    final String requestParam = get.substring(0, 1).toLowerCase() + get.substring(1);
                    final JsonElement jsonElement = jsonObject.get(requestParam);
                    final String param = jsonElement!=null?jsonElement.toString(): requestParam;
                    builder.add(param, (String) o);
                }

            }

            return builder.build();
        }
    }


    final static String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMfsxDoyU1t+DG0ZJd7DcpzmISQgsmjfHZHiJa0SFtKYSOGvs6Gr1EhlnUrS7SZgkgE2nRX1eVcmZ/bSCmlcV5kXkImLhL4cPsEXfR+LxgeLRDb0lDCrC6HS/0UGBkmVpP7tJm+DU4sE9+3Wk9IphtV5uPNiyaDBvgEu1B+wCfSFAgMBAAECgYEAwzuseGRy0JLsEZIQUFSu1RdKX9xqPU08tBySzEsw7GD4MySAl62T9Ur96nbGTcbabcLmbe40m22O8xI0RqV9h+7jct/2VBJZJzdpruGBBvD2x9d5hPfkMowexAx46fVbwwd80x4GP65LBJ41d9RzHvlzodIAV0OXCOpWs1+bcTUCQQD+32V3A1CevpwYwzbgE+2vA3bv9OyvqGR/+qMYUz2QNo+faPnq8itv3cZi58k7Qb8NY6PQs7AlE9eXOV73guOLAkEAyM8mfZD/8ydL/1OdNXE10RwgU5gLLfCVgSAk8AcQAx7XCUqlqyjA8BKiZJJJTNHN2QZGyLKqT6eAGqPcszRKLwJAVe1dGO2+LXbXy6VtB8jQNlP1slqhvWsJTvhiKh5OQCOU8kqDD4nLyTA85TV964Nz9QClxwP9m9J/udU2xj2TlwJBAJf31PxACMM+YRA4egfgxkabT4eT0BoTMUGITwvrfF2wMDKS8G9opyLIJ2ePIbPmLy9nxZfLRoKDk7oVekeQcfcCQBNAX/itcTa5xR/zz350Gq7UMGYCchTudyy3rD6i6dWGh/mtSMFJL8IbSF5W8LqNBKvqudAB39fYimqpC2FGWdw=";
}
